#include <QBuffer>
#include <QByteArray>
#include <QCryptographicHash>
#include <QDateTime>
#include <QDialogButtonBox>
#include <QFile>
#include <QFileDialog>
#include <QLineEdit>
#include <QMessageBox>
#include <QPixmap>
#include <QPushButton>
#include <QUuid>

#include "caddentrydialog.h"
#include "ui_caddentrydialog.h"

CAddEntryDialog::CAddEntryDialog(QString id, QString parent_name, QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::CAddEntryDialog), m_id(id), m_entry(0), m_downloader(new CDownloader)
{
    m_ui->setupUi(this);

    m_model = new CIconSelectionModel();
    m_ui->listView->setModel(m_model);

    if(parent_name.length())
        setWindowTitle(tr("Entry of %1").arg(parent_name));
    else
        setWindowTitle(tr("Error"));

    connect(m_ui->showPasswordBtn, SIGNAL(toggled(bool)), this, SLOT(showHidePassword(bool)));
    connect(m_ui->browseBtn, SIGNAL(clicked()), this, SLOT(openImage()));
    connect(m_ui->nameEdit, SIGNAL(textChanged(QString)), this, SLOT(checkFields()));
    connect(m_ui->loginEdit, SIGNAL(textChanged(QString)), this, SLOT(checkFields()));
    connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), this, SLOT(checkFields()));
    connect(m_ui->commentEdit, SIGNAL(textChanged(QString)), this, SLOT(checkFields()));
    connect(m_ui->listView, SIGNAL(pressed(QModelIndex)), this, SLOT(checkFields()));
    connect(m_ui->toolBox, SIGNAL(currentChanged(int)), this, SLOT(checkFields()));
    connect(m_ui->urlEdit,SIGNAL(textChanged(QString)), this, SLOT(urlChanged(QString)));
    connect(m_ui->downloadBtn, SIGNAL(clicked()), this, SLOT(downloadFavicon()));
    connect(m_downloader, SIGNAL(finished()), this, SLOT(downloadFinished()));

    connect(this, SIGNAL(accepted()), this, SLOT(process()));

    checkFields();
}

CAddEntryDialog::~CAddEntryDialog()
{
    delete m_ui;
}

void CAddEntryDialog::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void CAddEntryDialog::checkFields()
{
    bool result = m_ui->nameEdit->text().length() &&
                  ((!m_ui->toolBox->currentIndex() && m_ui->listView->currentIndex().isValid())
                   || (m_ui->toolBox->currentIndex() && m_ui->previewLbl->pixmap())
                   || (m_entry && m_entry->haveCustomIcon()));

    m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(result);
}

void CAddEntryDialog::showHidePassword(bool state)
{
    if(state)
        m_ui->passwordEdit->setEchoMode(QLineEdit::Normal);
    else
        m_ui->passwordEdit->setEchoMode(QLineEdit::Password);
}

bool CAddEntryDialog::loadIcon(QByteArray &arr)
{
    QPixmap pix;
    pix.loadFromData(arr);
    if(pix.isNull())
        return false;

    QByteArray data;
    QBuffer buf(&data);
    buf.open(QIODevice::WriteOnly);

    if(pix.width()>pix.height())
        pix.scaledToWidth(16).save(&buf, "PNG");
    else
        pix.scaledToHeight(16).save(&buf, "PNG");
    
    buf.close();
    pix.loadFromData(data);

    if(pix.isNull())
        return false;

    m_ui->previewLbl->setPixmap(pix);

    checkFields();

    return true;
}

void CAddEntryDialog::openImage()
{
    QString filename = QFileDialog::getOpenFileName(this, tr("Choose image file"), "", tr("Images (*.png *.jpg *.gif)"));
    if(!filename.length())
        return;

    QFile file(filename);
    if(!file.open(QIODevice::ReadOnly))
    {
        QMessageBox::critical(this, tr("Wrong file"), tr("Can't open specified file."));
        return;
    }

    QByteArray arr = file.readAll();
    file.close();

    if(loadIcon(arr))
        m_ui->pathEdit->setText(filename);
    else
    {
        QMessageBox::critical(this, tr("Wrong file"), tr("Can't open specified file."));
        return;
    }
}

void CAddEntryDialog::process()
{
    m_map.clear();

    if(!m_entry || m_ui->nameEdit->text()!=m_entry->getData(CEntry::Name).toString())
        m_map.insert(CEntry::getStringById(CEntry::Name), m_ui->nameEdit->text().toUtf8());

    if(!m_entry || m_ui->loginEdit->text()!=m_entry->getData(CEntry::Login).toString())
        m_map.insert(CEntry::getStringById(CEntry::Login), m_ui->loginEdit->text().toUtf8());

    if(!m_entry || m_ui->passwordEdit->text()!=m_entry->getData(CEntry::Password).toString())
        m_map.insert(CEntry::getStringById(CEntry::Password), m_ui->passwordEdit->text().toUtf8());

    if(!m_entry || m_ui->commentEdit->text()!=m_entry->getData(CEntry::Comments).toString())
        m_map.insert(CEntry::getStringById(CEntry::Comments), m_ui->commentEdit->text().toUtf8());

    if(m_entry)
    {
//        m_map.insert(CEntry::getStringById(CEntry::Id), m_entry->id());
//        m_map.insert(CEntry::getStringById(CEntry::Creation), m_entry->getData(CEntry::Creation));
//        m_map.insert(CEntry::getStringById(CEntry::Parent), m_entry->getData(CEntry::Parent));
    }
    else
    {
        m_map.insert(CEntry::getStringById(CEntry::Id), id());
        m_map.insert(CEntry::getStringById(CEntry::Creation), creation());
        m_map.insert(CEntry::getStringById(CEntry::Parent), m_id);
    }

    if(!m_ui->toolBox->currentIndex())
    {
        if(!m_ui->listView->currentIndex().isValid())
            m_map.insert(CEntry::getStringById(CEntry::IconId), QString());
        else
        {
            int row = m_ui->listView->currentIndex().row();
            m_map.insert(CEntry::getStringById(CEntry::IconId), m_model->nameById(row));
            if(m_entry)
                m_map.insert(CEntry::getStringById(CEntry::Icon), QVariant());
        }
    }
    else
    {
        if(m_ui->previewLbl->pixmap())
        {
/*            QFile file(m_ui->pathEdit->text());
            if(file.open(QIODevice::ReadOnly))
            {
                QByteArray data;
                QBuffer buf(&data);
                buf.open(QIODevice::WriteOnly);

                QPixmap pix;
                pix.loadFromData(file.readAll());
                if(pix.width()>pix.height())
                    pix.scaledToWidth(16).save(&buf, "PNG");
                else
                    pix.scaledToHeight(16).save(&buf, "PNG");

                buf.close();

                debug("data.size(): " + QString::number(data.size()));

                m_map.insert(CEntry::getStringById(CEntry::Icon), data);

                file.close();
            }
            else
                debug("Can't open file. Reason: " + file.errorString());*/

            QByteArray data;
            QBuffer buf(&data);
            buf.open(QIODevice::WriteOnly);

            if(m_ui->previewLbl->pixmap()->width()>m_ui->previewLbl->pixmap()->height())
                m_ui->previewLbl->pixmap()->scaledToWidth(16).save(&buf, "PNG");
            else
                m_ui->previewLbl->pixmap()->scaledToHeight(16).save(&buf, "PNG");
            buf.close();
            m_map.insert(CEntry::getStringById(CEntry::Icon), data);
        }
        else
            m_map.insert(CEntry::getStringById(CEntry::Icon), m_entry->getData(CEntry::Icon));
    }

    emit entry(this);
}

QStringList CAddEntryDialog::blobs()
{
    QStringList result;

//    if(m_map.contains(CEntry::getStringById(CEntry::Icon)))
        result << "*" + CEntry::getStringById(CEntry::Icon);

//    if(m_map.contains(CEntry::getStringById(CEntry::Login)))
        result << CEntry::getStringById(CEntry::Login);

//    if(m_map.contains(CEntry::getStringById(CEntry::Password)))
        result << CEntry::getStringById(CEntry::Password);

//    if(m_map.contains(CEntry::getStringById(CEntry::Comments)))
        result << CEntry::getStringById(CEntry::Comments);

//    if(m_map.contains(CEntry::getStringById(CEntry::Name)))
        result << CEntry::getStringById(CEntry::Name);

    return result;
}

QString CAddEntryDialog::id()
{
    if(m_entry)
        return m_entry->id();

    QCryptographicHash hash(QCryptographicHash::Md5);

    QUuid salt = QUuid::createUuid();

    QString str = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz") + salt.toString();
    QByteArray arr = str.toLatin1();

    hash.addData(arr);

    arr = hash.result();

    return QString(arr.toHex()).toUpper();
}

QString CAddEntryDialog::creation()
{
    if(m_entry)
        return m_entry->getData(CEntry::Creation).toString();

    return QDateTime::currentDateTime().toString(Qt::ISODate);
}

void CAddEntryDialog::setEntry(CEntry *e)
{
    if(!e)
        return;

    m_entry = e;

    m_ui->nameEdit->setText(e->getData(CEntry::Name).toString());
    m_ui->loginEdit->setText(e->getData(CEntry::Login, true).toString());
    m_ui->passwordEdit->setText(e->getData(CEntry::Password, true).toString());
    m_ui->commentEdit->setText(e->getData(CEntry::Comments).toString());
    if(e->haveCustomIcon())
    {       
        m_ui->previewLbl->setPixmap(qvariant_cast<QPixmap>(e->getData(CEntry::Icon)));
    }
    else
    {
        debug("Icon name: " + e->getData(CEntry::IconId).toString());
        m_ui->listView->setCurrentIndex(m_model->index(
                m_model->row(e->getData(CEntry::IconId).toString()), 0));
    }
}

void CAddEntryDialog::urlChanged(QString str)
{
    if(!str.length())
    {
        m_ui->downloadBtn->setEnabled(false);
        return;
    }

    m_ui->downloadBtn->setEnabled(true);
}

void CAddEntryDialog::downloadFavicon()
{
    QString host = m_ui->urlEdit->text();

    if(host.contains("://"))
    {
        host.remove(0, host.indexOf("://")+3);
    }

    while(host.endsWith("/"))
        host.remove(host.length()-1, 1);

    debug("host: " +  host);

    QUrl url("http://" + host + "/favicon.ico");

    debug(url.toString());

    m_downloader->doDownload(url);
}

void CAddEntryDialog::downloadFinished()
{
    if(m_downloader->is404())
    {
        QMessageBox::information(this, tr("File not found"), tr("Error 404 received: file favicon.ico not found"));
        return;
    }

    QByteArray arr = m_downloader->data();
    if(!loadIcon(arr))
        QMessageBox::critical(this, tr("Wrong image file"), tr("Can't load downloaded image. Try to add \"www\" prefix or smth else :)"));
}
